﻿using GameProject.Models;
using GameProject.Service;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using WebMatrix.WebData;

namespace GameProject.Service
{
	public class SnakesAndLadders
	{
		/// <summary>
		/// Dictionary to move the piece if it lands on a ladder or snake
		/// </summary>
		private static IDictionary<int, int> positionSnakesLadders = new Dictionary<int, int>()
		{
			{1,38},{4,14},{9,31},{17,7},{21,42},{28,84},{51,67},{54,34},{62,19},{64,60},{71,91},{80,100},{87,24},{93,73},{95,75},{98,79}
		};

		private GameInstanceService gameService;
		private GameInstance game;
		private bool gameOver;
		private int winnerId;
		private IDice dice;
		
		public int LastDiceResult { get; private set; }

		public int ExpectedNumberOfPlayers
		{
			get
			{ return game.ExpectedNumberOfPlayers; }
		}

		public int CurrentNumberOfPlayers
		{
			get
			{ return game.CurrentNumberOfPlayers; }
		}

		public SnakesAndLadders(int gameId, IDice d, GameInstanceService g)
		{
			gameService = g;
			dice = d;
			game = gameService.GetGameById(gameId);
		}

		public SnakesAndLadders(int gameId)
		{
			gameService = new GameInstanceService();
			dice = new Dice();
			game = gameService.GetGameById(gameId);
		}

		/// <summary>
		/// Bool function that returns true if current number of players are fewer than the expected number of players
		/// </summary>
		/// <returns>True or false</returns>
		public bool NotEnoughPlayers()
		{
			return game.CurrentNumberOfPlayers < game.ExpectedNumberOfPlayers;
		}

		/// <summary>
		/// Function that finds out what user is logged in and assigns him a piece
		/// </summary>
		public void AddUser()
		{
			game.CurrentNumberOfPlayers += 1;

			//Find out what user is logged in
			int currentUserId = WebSecurity.CurrentUserId;
			UserProfile userProfile = gameService.GetUserById(currentUserId);

			//For each player, create new Piece
			game.PieceSnakes.Add(new Piece() { User = userProfile });
			gameService.Save();
		}

		/// <summary>
		/// Function that returns true if the correct amount of players are in the game. 
		/// That is, if current number of players is equal to expected number of players.
		/// </summary>
		/// <returns>True or false</returns>
		public bool EnoughPlayers()
		{
			return game.CurrentNumberOfPlayers == game.ExpectedNumberOfPlayers;
		}

		/// <summary>
		/// Function that starts the game and saves it in the database.
		/// </summary>
		public void StartGame()
		{
			game.Status = GameStatus.PLAYING;
			gameService.Save();
		}

		/// <summary>
		/// Function that returns true if playing against the computer.
		/// </summary>
		/// <returns>True or false</returns>
		public bool PlayAgainstComputer()
		{
			return game.PlayAgainstComputer;
		}

		/// <summary>
		/// Function that lets you move the player
		/// </summary>
		/// <param name="playerId">The ID of the player</param>
		/// <returns>The locations of the player</returns>
		public List<int> MovePlayer(int playerId)
		{
			////Get random number for the dice
			LastDiceResult = dice.RollDice();

			//Get the old position of the player
			int oldLocation = game.PieceSnakes[playerId - 1].Position;
			//Get the new position(the old position + the dice result)
			int newLocation = oldLocation + LastDiceResult;

			//If the number the player gets from the dice puts him on square higher then 100, he must move the piece back
			if (newLocation > 100)
			{
				newLocation = 100 - (newLocation - 100);
			}

			//For the animation, "save" the locations
			List<int> locations = new List<int>();
			for (int i = oldLocation + 1; i <= newLocation; i++)
			{
				locations.Add(i);
			}

			//Move piece if it ends up on a ladder or a snake with the help of dictionary
			if (positionSnakesLadders.ContainsKey(newLocation))
			{
				newLocation = positionSnakesLadders[newLocation];
				locations.Add(newLocation);
			}
			
			//If the player lands on square 100 he is the winner and the game is over
			if (newLocation == 100)
			{
				gameOver = true;
				winnerId = playerId;

				game.Status = GameStatus.DONE;
			}

			//Change the new location and save it in the database
			game.PieceSnakes[playerId - 1].Position = newLocation;
			gameService.Save();

			return locations;
		}

		/// <summary>
		/// Bool function that returns true if the game is over
		/// </summary>
		/// <returns>True or false</returns>
		public bool IsGameOver()
		{
			return gameOver;
		}

		/// <summary>
		/// Function that returns the player ID of the next player
		/// </summary>
		/// <param name="playerId">The ID of the player</param>
		/// <returns></returns>
		public int GetNextPlayerId(int playerId)
		{
			//If the player gets 6 on the dice, it's his turn again.
			if (LastDiceResult == 6)
			{
				return playerId;
			}

			//Find the id of the next player
			int nextPlayerId = playerId + 1;

			if (nextPlayerId > game.ExpectedNumberOfPlayers)
			{
				nextPlayerId = 1;
			}

			return nextPlayerId;
		}
		
	}
}